package com.vipshop.compass.config;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.vipshop.compass.common.StringUtil;
import com.vipshop.compass.config.util.PrettyPrinter;
import com.vipshop.compass.config.util.PropertyUtility;

/**
 * Load the system properties from the XML file which be passed in as a VM
 * argument: </br> -Dconfig.filename=[your xml config file]</br> If you don't
 * specify this VM argument, it will load the default configuration file in the
 * classpath with name 'globals.config.xml'.
 * 
 * @author Levin
 * 
 */
public class Globals {
	/** Globals singleton instance */
	private static Globals globalsSingleton;

	private static Properties loadedProps;

	public static boolean containProperty(String key) {
		return System.getProperties().getProperty(key) != null;
	}

	/** Initial the Globals and the return the instance */
	public static Globals getInstance() {
		if (globalsSingleton == null) {
			globalsSingleton = new Globals();
			globalsSingleton.init();
		}
		return globalsSingleton;
	}

	public static String getProperty(String key) {
		return loadedProps.getProperty(key);
	}

	public static void main(String args[]) {

		System.out.println(Globals.getInstance().getProperty("com.vipshop.datasource.jndiDatasource.type"));
		Globals.setProperty("com.vipshop.datasource.jndiDatasource.type", "show the value");
	}

	public static void setProperty(String keyWord, String value) {
		PropertyUtility.setProperty(keyWord, value);
	}

	public Properties getAllProperties() {
		return this.loadedProps;
	}

	private void init() {
		loadedProps = new Properties();

		String originalFilename = PropertyUtility.getProperty("config.filename");
		if (StringUtil.isEmptyOrNull(originalFilename)) {
			throw new IllegalArgumentException("==>Please specify -Dconfig.filename VM argument!");
		}
		org.w3c.dom.Element ele = null;
		try {
			InputStream inputStream = new FileInputStream(originalFilename);
			InputSource isrc = new InputSource(inputStream);

			javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance();
			Document document = null;
			try {
				DocumentBuilder db = dbf.newDocumentBuilder();
				document = db.parse(isrc);
			} catch (ParserConfigurationException e) {
			} catch (SAXException e) {
			} catch (IOException e) {
			}
			try {
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			ele = document.getDocumentElement();
			PrettyPrinter.printNode(ele);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		NodeList sectionNodeList = ele.getElementsByTagName("section");
		List sectionList = new ArrayList();
		List entryList = new ArrayList();
		for (int i = 0; i < sectionNodeList.getLength(); i++) {
			Element sectionNode = (Element) sectionNodeList.item(i);
			String sectionString = sectionNode.getAttribute("name");
			if (sectionList.contains(sectionString)) {
				System.out.println("==>Defined duplicate section name: " + sectionString);
			}
			sectionList.add(sectionString);

			NodeList entryNodeList = sectionNode.getElementsByTagName("entry");
			for (int j = 0; j < entryNodeList.getLength(); j++) {
				Element entryNode = (Element) entryNodeList.item(j);
				String keyString = entryNode.getAttribute("key");
				if (entryList.contains(keyString)) {
					System.out.println("==>Defined duplicate entry name: " + keyString);
				}
				entryList.add(keyString);
				// If not value attribute is supplied, make it null
				String valueString = null;
				if (entryNode.getAttributeNode("value") != null) {
					valueString = entryNode.getAttribute("value");
				}
				loadedProps.put(keyString, valueString);
				//System.out.println("key: " + keyString + "  value: " + valueString);
			}
		}
	}

}
